package jodd.http;

import archer.framework.protocol.ArcherProtocolModule;
import archer.framework.test.support.TestConfig;
import archer.framework.utils.HttpUtils;
import archer.framework.utils.SignatureUtils;
import archer.framework.utils.ValidateUtils;
import jodd.http.up.Uploadable;
import jodd.util.URLDecoder;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

/**
 * 调试用途的HttpRequest
 *
 * @author christ
 * @date 2015/7/21
 */
public class HttpRequestForDebug extends HttpRequest {

    /**
     * 参数签名处理
     *
     * @return
     */
    public HttpRequestForDebug sign() {

        String apisecret = TestConfig.getConfig("test.api.apisecret");

        String signField = ArcherProtocolModule.signatureField;

        if (this.method().toUpperCase().equals("POST")) {
            this.form(signField, SignatureUtils.genSignature(HttpUtils.asParameterMap(this.form()), apisecret, signField));
        } else {
            this.query(signField, SignatureUtils.genSignature(HttpUtils.asParameterMap(this.query()), apisecret, signField));
        }

        return this;
    }

    /**
     * Builds a CONNECT request.
     */
    public static HttpRequest connect(String destination) {
        return new HttpRequestForDebug()
                .method("CONNECT")
                .set(destination);
    }

    /**
     * Builds a GET request.
     */
    public static HttpRequest get(String destination) {
        return new HttpRequestForDebug()
                .method("GET")
                .set(destination);
    }

    /**
     * Builds a POST request.
     */
    public static HttpRequest post(String destination) {
        return new HttpRequestForDebug()
                .method("POST")
                .set(destination);
    }

    /**
     * Builds a PUT request.
     */
    public static HttpRequest put(String destination) {
        return new HttpRequestForDebug()
                .method("PUT")
                .set(destination);
    }

    /**
     * Builds a PATCH request.
     */
    public static HttpRequest patch(String destination) {
        return new HttpRequestForDebug()
                .method("PATCH")
                .set(destination);
    }

    /**
     * Builds a DELETE request.
     */
    public static HttpRequest delete(String destination) {
        return new HttpRequestForDebug()
                .method("DELETE")
                .set(destination);
    }

    /**
     * Builds a HEAD request.
     */
    public static HttpRequest head(String destination) {
        return new HttpRequestForDebug()
                .method("HEAD")
                .set(destination);
    }

    /**
     * Builds a TRACE request.
     */
    public static HttpRequest trace(String destination) {
        return new HttpRequestForDebug()
                .method("TRACE")
                .set(destination);
    }

    /**
     * Builds an OPTIONS request.
     */
    public static HttpRequest options(String destination) {
        return new HttpRequestForDebug()
                .method("OPTIONS")
                .set(destination);
    }

    /**
     * 是否包含文件参数
     *
     * @return
     */
    private boolean containsFileParam() {
        Map<String, Object[]> formParam = HttpUtils.asParameterMap(this.form());

        if (formParam == null) {
            return false;
        }

        for (String param : formParam.keySet()) {
            if (ValidateUtils.isNotEmpty(formParam.get(param)) && formParam.get(param)[0] instanceof Uploadable) {
                return true;
            }
        }
        return false;
    }

    @Override
    public HttpResponseForDebug send() {

        System.out.println("==================================================================>>");

        // 如果包含文件参数则不进行decode操作，因为二进制decode会出错
        if (!containsFileParam()) {
            System.out.println(URLDecoder.decodeQuery(this.toString(), "UTF-8"));
        }

        if (httpConnection == null) {
            open();
        }

        // prepare http connection

        if (timeout != -1) {
            httpConnection.setTimeout(timeout);
        }

        // sends data
        HttpResponse httpResponse;
        try {
            OutputStream outputStream = httpConnection.getOutputStream();

            sendTo(outputStream);

            InputStream inputStream = httpConnection.getInputStream();

            httpResponse = HttpResponseForDebug.readFrom(inputStream);

            httpResponse.assignHttpRequest(this);
        } catch (IOException ioex) {
            throw new HttpException(ioex);
        }

        boolean keepAlive = httpResponse.isConnectionPersistent();

        if (keepAlive == false) {
            // closes connection if keep alive is false, or if counter reached 0
            httpConnection.close();
            httpConnection = null;
        }

        return (HttpResponseForDebug) httpResponse;
    }

    @Override
    public HttpRequestForDebug query(String name, String value) {
        return (HttpRequestForDebug) super.query(name, value);
    }

    @Override
    public HttpRequestForDebug form(String name, Object value) {
        return (HttpRequestForDebug) super.form(name, value);
    }

    public HttpRequestForDebug form(Map<String, Object> formMap) {
        return (HttpRequestForDebug) super.form(formMap);
    }

    public HttpRequestForDebug form(String name, Object value, Object... parameters) {
        return (HttpRequestForDebug) super.form(name, value, parameters);
    }

    public HttpRequestForDebug form(String name, Object value, boolean overwrite) {
        return (HttpRequestForDebug) super.form(name, value, overwrite);
    }

    public HttpRequestForDebug body(String body) {
        return (HttpRequestForDebug) super.body(body);
    }

    public HttpRequestForDebug bodyText(String body, String mediaType, String charset) {
        return (HttpRequestForDebug) super.bodyText(body, mediaType, charset);
    }
}
